import Taro from '@tarojs/taro'
import { execObject, SelectorQuery } from '@tarojs/taro/types/index'

function delay(delayTime = 500): Promise<null> {
  return new Promise(resolve => {
    if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'swan') {
      setTimeout(() => {
        resolve()
      }, delayTime)
      return
    }
    resolve()
  })
}

function delayQuerySelector(
  self,
  selectorStr: string,
  delayTime = 500
): Promise<Array<execObject>> {
  const $scope = process.env.TARO_ENV === 'h5' ? self : self.$scope
  const selector: SelectorQuery = Taro.createSelectorQuery().in($scope)

  return new Promise(resolve => {
    delay(delayTime).then(() => {
      selector
        .select(selectorStr)
        .boundingClientRect()
        .exec((res: Array<execObject>) => {
          resolve(res)
        })
    })
  })
}

function delayGetScrollOffset({ delayTime = 500 }): Promise<Array<execObject>> {
  return new Promise(resolve => {
    delay(delayTime).then(() => {
      Taro.createSelectorQuery()
        .selectViewport()
        .scrollOffset()
        .exec((res: Array<execObject>) => {
          resolve(res)
        })
    })
  })
}

function delayGetClientRect({ self, selectorStr, delayTime = 500 }): Promise<Array<execObject>> {
  const $scope =
    process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'swan' ? self : self.$scope
  const selector: SelectorQuery = Taro.createSelectorQuery().in($scope)

  return new Promise(resolve => {
    delay(delayTime).then(() => {
      selector
        .select(selectorStr)
        .boundingClientRect()
        .exec((res: Array<execObject>) => {
          resolve(res)
        })
    })
  })
}

function uuid(len = 8, radix = 16): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
  const value: string[] = []
  let i = 0
  radix = radix || chars.length

  if (len) {
    // Compact form
    for (i = 0; i < len; i++) value[i] = chars[0 | (Math.random() * radix)]
  } else {
    // rfc4122, version 4 form
    let r

    // rfc4122 requires these characters
    /* eslint-disable-next-line */
    value[8] = value[13] = value[18] = value[23] = '-'
    value[14] = '4'

    // Fill in random data.  At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (i = 0; i < 36; i++) {
      if (!value[i]) {
        r = 0 | (Math.random() * 16)
        value[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r]
      }
    }
  }

  return value.join('')
}

interface EventDetail {
  pageX: number
  pageY: number
  clientX: number
  clientY: number
  offsetX: number
  offsetY: number
  x: number
  y: number
}

function getEventDetail(event: any) {
  let detail: EventDetail
  switch (process.env.TARO_ENV) {
    case 'h5': {
      // event.persist()
      detail = {
        pageX: event.nativeEvent.pageX,
        pageY: event.nativeEvent.pageY,
        clientX: event.nativeEvent.clientX,
        clientY: event.nativeEvent.clientY,
        offsetX: event.nativeEvent.offsetX,
        offsetY: event.nativeEvent.offsetY,
        x: event.nativeEvent.x,
        y: event.nativeEvent.y
      }
      break
    }

    case 'weapp':
      detail = {
        pageX: event.touches[0].pageX,
        pageY: event.touches[0].pageY,
        clientX: event.touches[0].clientX,
        clientY: event.touches[0].clientY,
        offsetX: event.target.offsetLeft,
        offsetY: event.target.offsetTop,
        x: event.target.x,
        y: event.target.y
      }
      break

    case 'alipay':
      detail = {
        pageX: event.target.pageX,
        pageY: event.target.pageY,
        clientX: event.target.clientX,
        clientY: event.target.clientY,
        offsetX: event.target.offsetLeft,
        offsetY: event.target.offsetTop,
        x: event.target.x,
        y: event.target.y
      }
      break

    case 'swan':
      detail = {
        pageX: event.changedTouches[0].pageX,
        pageY: event.changedTouches[0].pageY,
        clientX: event.target.clientX,
        clientY: event.target.clientY,
        offsetX: event.target.offsetLeft,
        offsetY: event.target.offsetTop,
        x: event.detail.x,
        y: event.detail.y
      }
      break

    default:
      detail = {
        pageX: 0,
        pageY: 0,
        clientX: 0,
        clientY: 0,
        offsetX: 0,
        offsetY: 0,
        x: 0,
        y: 0
      }
      console.warn('getEventDetail暂未支持该环境')
      break
  }
  return detail
}

function initTestEnv() {
  if (process.env.NODE_ENV === 'test') {
    Taro.initPxTransform({ designWidth: 750 })
  }
}

function isTest() {
  return process.env.NODE_ENV === 'test'
}
// 是否是钉钉环境
function isDD() {
  if (process.env.TARO_ENV === 'alipay' && !Taro.canIUse('optionsSelect')) {
    return true
  }
  return false
}
let scrollTop = 0

function handleTouchScroll(flag) {
  if (process.env.TARO_ENV !== 'h5') {
    return
  }
  if (flag) {
    scrollTop = document.documentElement.scrollTop

    // 使body脱离文档流
    document.body.classList.add('at-frozen')

    // 把脱离文档流的body拉上去！否则页面会回到顶部！
    document.body.style.top = `${-scrollTop}px`
  } else {
    document.body.style.top = null
    document.body.classList.remove('at-frozen')

    document.documentElement.scrollTop = scrollTop
  }
}

function pxTransform(size) {
  if (!size) return ''
  return Taro.pxTransform(size)
}
const objectToString = style => {
  if (style && typeof style === 'object') {
    let styleStr = ''
    Object.keys(style).forEach(key => {
      const lowerCaseKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()
      styleStr += `${lowerCaseKey}:${style[key]};`
    })
    return styleStr
  } else if (style && typeof style === 'string') {
    return style
  }
  return ''
}

const formatTime = time => {
  // 如果是hls视频时，初始获取到的时长会是Infinity，会返回NaN
  if (time === null || !Number.isFinite(time)) return ''
  const sec = Math.round(time % 60)
  const min = Math.round((time - sec) / 60)
  return `${min < 10 ? `0${min}` : min}:${sec < 10 ? `0${sec}` : sec}`
}

export {
  objectToString,
  delay,
  delayQuerySelector,
  uuid,
  getEventDetail,
  initTestEnv,
  isTest,
  isDD,
  pxTransform,
  handleTouchScroll,
  delayGetClientRect,
  delayGetScrollOffset,
  formatTime
}
